package main

import (
	"consul_grpc/config"
	"consul_grpc/discover"
	"consul_grpc/endpoint"
	grpc_health_v1 "consul_grpc/grpc.health.v1"
	"consul_grpc/pb"
	"consul_grpc/plugins"
	"consul_grpc/service"
	"consul_grpc/transport"
	"context"
	"flag"
	"fmt"
	"net"
	"os"
	"os/signal"
	"strconv"
	"syscall"

	uuid "github.com/satori/go.uuid"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

func main() {
	var (
		//服务地址
		servicePort = flag.Int("service.port", 10086, "service port")
		serviceHost = flag.String("service.host", "127.0.0.1", "service host")
		serviceName = flag.String("service.name", "Consul-Grpc", "service name")

		//consul地址
		consulPost = flag.Int("consul.port", 8500, "consul port")
		consulHost = flag.String("consul.host", "127.0.0.1", "consul host")
	)
	flag.Parse()
	ctx := context.Background()
	errChan := make(chan error)

	//初始化一个go-kit的Consul服务Client
	discoverClient, err := discover.NewKitDiscoverClient(*consulHost, *consulPost)
	if err != nil {
		config.Logger.Println(err.Error())
		return
	}

	//初始化一个服务逻辑实现
	var srv = service.NewServiceImpl(discoverClient)

	//日志中间件封装srv
	srv = plugins.LoggingMiddleware(config.KitLogger)(srv)

	//建立对应各服务的Endpoint实例
	healthCheckEndpoint := endpoint.MakeHealthCheckEndpoint(srv)
	greettEndpoint := endpoint.MakeGreetEndpoint(srv)
	discoveryEndpoint := endpoint.MakeDiscoveryEndpoint(srv)

	//利用各服务的Endpoint实例初始化一个Endpoint实例集
	endpts := endpoint.ConsulGrpcEndpoint{
		HealthEndpoint:    healthCheckEndpoint,
		GreetEndpoint:     greettEndpoint,
		DiscoveryEndpoint: discoveryEndpoint,
	}

	//初始化一个Grpc服务处理实例，需传入ConsulGrpcEndpoint实例，具体实现由ConsulGrpcEndpoint决定
	handler := transport.NewGrpcServer(ctx, endpts)

	//生成要给服务ID
	instanceId := *serviceName + "-" + uuid.NewV4().String()

	//Grpc启动协程
	go func() {
		config.Logger.Println("Grpc Server start at port:" + strconv.Itoa(*servicePort))
		//在启动之前先在Consul进行注册，注册成功在进行下一步
		if !discoverClient.Register(*serviceName, instanceId, "/Health", *serviceHost, *servicePort, nil, config.Logger) {
			config.Logger.Printf("Grpc Server for service %s failed.", *serviceName)
			os.Exit(-1)
		}
		//初始化一个Grpc的Server
		grpcServer := grpc.NewServer()
		list, err := net.Listen("tcp", ":10086") //监听端口
		if err != nil {
			panic(err.Error())
		}
		///注册具体服务
		pb.RegisterConsulGrpcServerServer(grpcServer, handler)
		//grpcurl接口反射注册
		reflection.Register(grpcServer)
		//健康检测注册，Consul能否检查该服务是否正常基于这个注册，与上面的具体服务注册使用同一个Grpc的Server
		grpc_health_v1.RegisterHealthServer(grpcServer, transport.NewGrpcHealthV1Server())
		//启动服务
		grpcServer.Serve(list)
	}()

	//服务退出监控协程
	go func() {
		c := make(chan os.Signal, 1)
		signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
		errChan <- fmt.Errorf("%s", <-c)
	}()

	//阻塞，待是否结束提供服务
	err = <-errChan
	//若结束提供服务则进行Consul的服务注销
	discoverClient.DeRegister(instanceId, config.Logger)
	config.Logger.Println(err)
}
